package com.spider.im.common.security;

import com.spider.im.common.aspect.BusinessException;
import com.spider.im.common.constant.RedisKey;
import com.spider.im.common.constant.RespCodeEnum;
import com.spider.im.login.enums.LoginTypeEnum;
import com.spider.im.login.req.LoginReq;
import com.spider.im.login.resp.LoginUser;
import com.spider.im.user.resp.UserResp;
import io.jsonwebtoken.*;
import io.jsonwebtoken.security.Keys;
import jakarta.annotation.Resource;
import org.redisson.api.RBucket;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Component;

import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import java.security.Key;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;

@Component
public class JwtUtil {

    // 提取密钥到配置文件中
    @Value("${secret_key:27NsKpxSagDd763noxHpWn4uGG1i05XqAV64ca11fIQ=}")
    private String secretKey;

    // 过期时间30天
    @Value("${token_expiration_time:2592000000}")
    private Long tokenExpirationTime;

    @Resource
    private RedissonClient redissonClient;

    /**
     * 从令牌中提取用户名
     */
    public String extractUsername(String token) {
        return extractClaim(token, Claims::getSubject);
    }

    /**
     * 从令牌中提取过期时间
     */
    public Date extractExpiration(String token) {
        return extractClaim(token, Claims::getExpiration);
    }

    /**
     * 通用方法：从令牌中提取指定的声明信息
     */
    public <T> T extractClaim(String token, Function<Claims, T> claimsResolver) {
        final Claims claims = extractAllClaims(token);
        return claimsResolver.apply(claims);
    }

    /**
     * 解析并提取所有声明信息
     */
    private Claims extractAllClaims(String token) {

        Key key = Keys.hmacShaKeyFor(secretKey.getBytes());
        return Jwts.parser()
                .setSigningKey(key)
                .build()
                .parseSignedClaims(token)
                .getPayload();
    }

    /**
     * 判断令牌是否已过期
     */
    private Boolean isTokenExpired(String token) {
        Date expiration = extractExpiration(token);
        return expiration.before(new Date());
    }

    /**
     * 生成新的JWT令牌
     */
    public String generateToken(UserResp userResp) {
        Map<String, Object> claims = new HashMap<>();
        String userId = userResp.getId().toString();
        String token = createToken(claims, userId);
        // 存储 token 到 Redis
        RBucket<String> bucket = redissonClient.getBucket(RedisKey.USER_TOKEN_KEY + userId);
        bucket.set(token, tokenExpirationTime, TimeUnit.MILLISECONDS);
        return token;
    }

    /**
     * 创建JWT令牌
     */
    private String createToken(Map<String, Object> claims, String subject) {

        // 显式指定算法
        return Jwts.builder()
                .claims(claims)
                .subject(subject)
                .issuedAt(new Date(System.currentTimeMillis()))
                .expiration(new Date(System.currentTimeMillis() + tokenExpirationTime))
                // 使用 Jwts.SIG.HS256 替代 SignatureAlgorithm.HS256
                .signWith(Keys.hmacShaKeyFor(secretKey.getBytes()), Jwts.SIG.HS256)
                .compact();
    }

    /**
     * 验证令牌的有效性
     */
    public Boolean validateToken(String token, LoginUser userDetails) {
        if (userDetails == null || userDetails.getUserResp() == null) {
            return false; // 如果用户信息为空，直接返回无效
        }
        String userId = userDetails.getUserResp().getId().toString();

        // 从 Redis 获取存储的 token
        RBucket<String> bucket = redissonClient.getBucket(RedisKey.USER_TOKEN_KEY + userId);
        String storedToken = bucket.get();
        if (storedToken == null || !storedToken.equals(token)) {
            return false; // token 不匹配或未找到
        }
        String userIdToken = extractUsername(token);
        if (userIdToken == null || !userIdToken.equals(userId)) {
            return false; // 用户不匹配
        }
        return !isTokenExpired(token);
    }

    public static String getEncodeKey() throws NoSuchAlgorithmException {
        // 创建AES密钥生成器
        KeyGenerator keyGen = KeyGenerator.getInstance("AES");
        keyGen.init(256); // 使用128位密钥

        // 生成密钥
        SecretKey secretKey = keyGen.generateKey();

        // 将密钥转换为Base64编码字符串
//        String encodedKey = Base64.getEncoder().encodeToString(secretKey.getEncoded());
        return Base64.getEncoder().encodeToString(secretKey.getEncoded());

    }
    public static void main(String[] args) throws NoSuchAlgorithmException {

        System.out.println("Generated Secret Key (Base64): " + JwtUtil.getEncodeKey());
    }
}
